[レポート] ワークショップ – GitHub Actionsを使ったIAMポリシーの検証と分析の自動化 #IAM452 #AWSreInforce
あしざわです。
米国フィラデルフィアで開催されている AWS re:Inforce 2024 に参加しています。
本記事は AWS re:Inforce 2024 のワークショップ 「Automating IAM Policy Validation and Analysis using GitHub Actions」のレポートです。
セッション概要
In this builders’ session, learn how to automate the validation of AWS Identity and Access Management (IAM) policies using the IAM Policy Validator for AWS CloudFormation (cfn-policy-validator). Policy validation and analysis minimize the deployment of unwanted IAM policies. While security teams oversee the organizational security posture, developers create applications that need permissions. To help developers work quickly without compromising on security posture, organizations delegate developer IAM policy authoring. By combining automated validation and analysis with delegated developer permissions, organizations can gain more secure development velocity. Learn how cfn-policy-validator and GitHub Actions can automatically validate and analyze IAM policies when permitting developer policy authoring abilities without compromising security. You must bring your laptop to participate.
ワークショップで体験したこと
このワークショップでは、GitHub Actionsを用いてCloudFormationテンプレートで定義されたIAMリソースの自動ポリシーチェックを体験できました。
全体の流れを簡単に説明したものがこちらです。
- Sagemaker StudioからGitHub上のリポジトリにCloudFormationテンプレートをCommit/Pushします
- リポジトリに設定されたGitHub Actionワークフローがトリガーされます
- ワークフローの中でIAM Access Analyzer のカスタムポリシーチェック(CheckNoNewAccess)が動作します
- チェック結果がPassとなればOK、FailedとなればNGです
CheckNoNewAccessとは、IAM Access Analyzerのカスタムポリシーチェックの1種です。既存のポリシーと比較して、更新されたポリシーに対して新しいアクセスが許可されているかどうかを確認できます。通常、既存のポリシー・更新されたポリシーの両方をJSONのIAMポリシーの形式でファイルとして保存し、比較する必要があります。
## AWS CLIで実行する場合のイメージ aws accessanalyzer check-no-new-access \ --existing-policy-document file://existing-policy.json \ ##既存のポリシー --new-policy-document file://new-policy.json \ ##更新されたポリシー --policy-type IDENTITY_POLICY
今回のワークショップでは、aws-cloudformation-iam-policy-validator
というawslabsのGitHubリポジトリで継続的に更新されているツール利用します。このツールを利用すれば、CheckNoNewAccessによる比較対象としてCloudFormationテンプレートを指定できます。
ここでは前者の既存のポリシー(--existing-policy-document
)をリファレンスファイルとして事前にS3バケットに保存し、後者の更新されたポリシー(--new-policy-document
)としてGitHubリポジトリにCommit&PushされたCFnテンプレートを利用します。
システム構成図
全体のシステム構成図はこちら。
ワークショップの流れ
ワークショップは、事前準備・課題1・課題2という3つのフェーズで構成されていました。
課題フェーズは2つのパターンがありましたが、多少リファレンスファイルやCFnテンプレートの内容に差があるくらいで対応する流れは同様でした。なので、レポートは課題1のみとし、課題2についてはこのレポートで記載しません。
事前準備
事前準備フェーズでは、こちらの作業を行いました。
- GitHubリポジトリの作成
- Sagemaker Studio のCode Editor で作成したリポジトリをClone
- GitHub Actions用のAWSクレデンシャルを発行
- IAM Access Analyzer APIを呼び出すためのIAMロールを作成
1、2については特に目新しいことはやっていないので割愛します。
3では、まずIAMのIDプロバイダにGitHub Actions用のプロバイダ( https://token.actions.githubusercontent.com
)を作成し、対象をSTS( sts.amazonaws.com
)とします。
4では、まず作成したIDプロバイダのプロバイダ名と対象者(Audience)、GitHubユーザー名(もしくはOrganization名)、GitHubリポジトリ名を入力して、IAMロールを作成します
ここでGitHubリポジトリがプライベート設定だった場合、GitHub Actions用のSecretとして追加の設定が必要になります。対象のGitHubリポジトリのSettings > Security > Secrets and variables > Actions
から以下を設定してください。
- Name:
OIDC_IAM_ROLE
- Secret:
arn:aws:iam::<accountID>:role/<rolename>
準備は以上です。
課題
ここからがワークショップの本題である課題フェーズです。
本題と言いながら再び環境構築フェーズです。
まずはSagemaker StudioのCode Editorを利用して、各ファイルを作成していきます。
※
name: cfn-policy-validator-workflow on: pull_request: types: [opened, review_requested] push: branches: - 'main' permissions: id-token: write contents: read issues: write jobs: cfn-iam-policy-validation: name: iam-policy-validation runs-on: ubuntu-latest permissions: write-all steps: - name: Checkout code id: checkOut uses: actions/checkout@v4 - name: Configure AWS Credentials id: configureCreds uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: ${{ secrets.OIDC_IAM_ROLE }} aws-region: <AWSRegion> ##<AWSRegion>には利用中のリージョンを入力 role-session-name: GitHubSessionName - name: Fetch reference policy from s3 id: getReferencePolicy run: | aws s3 cp ${{ secrets.REFERENCE_IDENTITY_POLICY }} ./reference-identity-policy.json shell: bash - name: Run AWS AccessAnalyzer CheckNoNewAccess check id: run-aws-check-no-new-access uses: aws-actions/cloudformation-aws-iam-policy-validator@v1.0.1 with: policy-check-type: 'CHECK_NO_NEW_ACCESS' template-path: './sample-role.yaml' reference-policy: './reference-identity-policy.json' reference-policy-type: "IDENTITY" region: <AWSRegion> ##<AWSRegion>には利用中のリージョンを入力
次はリファレンスファイルを作成、S3バケットに配置します。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "*", "Resource": "*" }, { "Effect": "Deny", "Action": "iam:PassRole", "Resource": "arn:aws:iam::*:role/my-sensitive-roles/*" } ] }
続いて、GitHub Secretにリファレンスポリシーを配置したS3のURLなどを設定します。
- Name:
REFERENCE_IDENTITY_POLICY
- Secret:
s3://<ConfigBucket>/reference-identity-policy.json
この環境に対し、以下のファイルを作成し、Commit/Pushします。
AWSTemplateFormatVersion: "2010-09-09" Description: IAM452 Sample CloudFormation Resources: SampleIamRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Statement: - Effect: Allow Principal: AWS: "*" Action: ["sts:AssumeRole"] Path: / Policies: - PolicyName: root PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - "dynamodb:Scan" - "dynamodb:Query" - "dynamodb:UpdateItem" - "dynamodb:GetItem" - "dynamodb:DeleteTable" Resource: "*" - Effect: Allow Action: - "iam:PassRole" Resource: "arn:aws:iam::*:role/my-sensitive-roles/adminrole452"
すると、エラーになりました。何が問題だったのでしょうか???
※Run AWS AccessAnalyzer CheckNoNewAccess check
で出ていたエラー内容がこちらです。
result={"BlockingFindings": [{"findingType": "SECURITY_WARNING","code": "policy-analysis-CheckNoNewAccess","message": "The modified permissions grant new access compared to your existing policy.","resourceName": "SampleIamRole","policyName": "root","details": {"result": "FAIL","message": "The modified permissions grant new access compared to your existing policy.","reasons": [{"description": "New access in the statement with index: 1.","statementIndex": 1}]}}],"NonBlockingFindings": []}
問題はこの箇所にありました。
- Effect: Allow Action: - "iam:PassRole" Resource: "arn:aws:iam::*:role/my-sensitive-roles/adminrole452"
リファレンスファイルではarn:aws:iam::*:role/my-sensitive-roles/*
はDenyされているので、「〜my-sensitive-roles/adminrole452」がAllowされてしまっているCFnテンプレートでは権限を超えてしまう(NewAccessが生まれてしまう)わけです。なので、CheckNoNewAccessで違反となります。
{ "Effect": "Deny", "Action": "iam:PassRole", "Resource": "arn:aws:iam::*:role/my-sensitive-roles/*" }
該当の箇所をセクションごと削除して以下のファイルに修正し、再度Commit&Pushしました。
AWSTemplateFormatVersion: "2010-09-09" Description: IAM452 Sample CloudFormation Resources: SampleIamRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Statement: - Effect: Allow Principal: AWS: "*" Action: ["sts:AssumeRole"] Path: / Policies: - PolicyName: root PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - "dynamodb:Scan" - "dynamodb:Query" - "dynamodb:UpdateItem" - "dynamodb:GetItem" - "dynamodb:DeleteTable" Resource: "*"
ワークフローが実行され、次はエラーが解消されていました。
おわりに
以上、「Automating IAM Policy Validation and Analysis using GitHub Actions」のレポートでした。
GitHub ActionsおよびIAM Access Analyzerをあまり使ったことがなかったため、入門ワークショップとして最適なセッションでした。非常に参考になりました。
今回のre:Inforceでは、ポリシーを自動チェック・デプロイする仕組みとして以下の構成を設定し、SCPを安全にデプロイする構成を紹介するセッションがありました。
- CI/CDパイプライン: CodePipeline
- ビルド: CodeBuild
- ポリシーチェック: terraform-iam-policy-validator
terraform-iam-policy-validator
は本セッションでも紹介されていた、CFnテンプレートではなくTerraformテンプレートをIAMポリシーの解析対象として分析できるツールです。Terraformを利用しているプロジェクトに自動ポリシーチェックの仕組みを導入する場合はこちらの方がマッチしそうです。
紹介した別セッションのレポートもブログにしていますので合わせてご覧ください。
あしざわでした。